package com.ft.security.filter;

import com.ft.core.exceptions.AuthorizationExpiredException;
import com.ft.core.runtime.session.IAuthUser;
import com.ft.security.SecurityConstants;
import com.ft.security.config.JwtProperties;
import com.ft.security.utils.JwtTokenUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Collection;

/**
 * @copyright (C), 2015-2019, XXX有限公司
 * @fileName: JwtAuthenticationTokenFilter
 * @author: 李阳
 * @date: 2019/5/13 16:56
 * @description: token 过滤器，在这里解析token，拿到该用户角色，设置到SpringSecurity的上下文环境中，让SpringSecurity自动判断权限
 * 所有请求最先进入此过滤器，包括登录接口，而且在SpringSecurity的密码验证之前执行
 * @history: <author>          <time>          <version>          <desc>
 * 作者姓名           修改时间           版本号              描述
 */
@Component
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {

    //@Resource
    //private IAuthService authService;

    @Autowired
    private JwtProperties jwtProperties;

    @Autowired
    private JwtTokenUtil jwtTokenUtil;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException {
        // 如果是登录页则不进入处理
        if (!SecurityConstants.OAUTH_TOKEN_LOGIN_URL.equals(request.getRequestURI())) {
            String authHeader = request.getHeader(jwtProperties.getHeader());

            if (authHeader != null && authHeader.startsWith(jwtProperties.getTokenPrefix())) {
                String authToken = authHeader.replace(jwtProperties.getTokenPrefix(), "");
                String username = jwtTokenUtil.getUsernameFromToken(authToken);
                Long tenantId = jwtTokenUtil.getTenantIdFromToken(authToken);
                // 验证token,具体怎么验证看需求，可以只验证token不查库，把权限放在jwt中即可
                // JwtUser userDetails = authService.loadUserByUsername(username, tenantId);

                if (!jwtTokenUtil.validateToken(authToken)) {
                    throw new AuthorizationExpiredException("token已过期");
                } else {
                    final IAuthUser authUser = jwtTokenUtil.toAuthUser(authToken);
                    final Collection<? extends GrantedAuthority> authorities = jwtTokenUtil.getAuthorities(authToken);
                    // 这里只要告诉SpringSecurity权限即可，账户密码就不用提供验证了，这里我们把UserDetails传给SpringSecurity，以便以后我们获取当前登录用户
                    UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(authUser, null, authorities);
                    authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
                    logger.info(String.format("Authenticated userDetail %s, setting security context", username));
                    SecurityContextHolder.getContext().setAuthentication(authentication);
                }
            }
        }

        chain.doFilter(request, response);
    }
}
